package com.zrkizzy.module.system.service.common;

import com.zrkizzy.common.core.constant.HttpConst;
import com.zrkizzy.common.core.constant.TimeConst;
import com.zrkizzy.common.core.utils.IpUtil;
import com.zrkizzy.common.core.utils.ServletUtil;
import com.zrkizzy.common.models.domain.system.core.User;
import com.zrkizzy.common.models.dto.system.common.LoginDTO;
import com.zrkizzy.common.redis.service.IRedisService;
import com.zrkizzy.common.security.context.SecurityContext;
import com.zrkizzy.common.security.context.UserContext;
import com.zrkizzy.common.security.utils.JwtTokenUtil;
import com.zrkizzy.system.facade.service.common.ILoginService;
import com.zrkizzy.module.system.filter.LoginFilter;
import eu.bitwalker.useragentutils.UserAgent;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import static com.zrkizzy.common.redis.enums.RedisKey.USER_KEY;

/**
 * 登录业务逻辑接口实现类
 *
 * @author zhangrongkang
 * @since 2023/8/30
 */
@Slf4j
@Service
public class LoginServiceImpl implements ILoginService {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private IRedisService redisService;

    @Autowired
    private LoginFilter loginFilter;

    /**
     * 用户登录
     *
     * @param loginDTO 用户登录数据传输对象
     * @return Token
     */
    @Override
    public String processLogin(LoginDTO loginDTO) {
        // 如果执行完责任链后未抛出异常则说明校验通过
        loginFilter.handleLogin(loginDTO);
        // 从上下文中获取用户变量
        User user = UserContext.getUser();
        // 封装用户对象
        setUserAttributeValue(user, loginDTO.getTraceId());
        // 存在则将获取到的用户信息存储到Redis中，过期时间为两小时
        redisService.set(USER_KEY.getKey() + loginDTO.getTraceId(), user, TimeConst.TWO_HOUR);
        // 根据用户登录唯一标识生成Token
        return jwtTokenUtil.generateToken(loginDTO.getTraceId());
    }

    /**
     * 设置用户属性值
     *
     * @param user 用户对象
     * @param traceId 用户登录唯一标识
     */
    private void setUserAttributeValue(User user, String traceId) {
        HttpServletRequest request = ServletUtil.getRequest();
        // 获取用户登录设备信息对象
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader(HttpConst.USER_AGENT));
        // 获取IP地址
        String ipAddress = IpUtil.getIpAddress(request);
        // Redis中不显示密码
        user.setPassword(null);
        // 设置当前用户登录时间
        user.setLoginTime(LocalDateTime.now());
        // 登录IP
        user.setIpAddress(ipAddress);
        // 登录位置
        user.setIpLocation(IpUtil.getIpLocation(ipAddress));
        // 用户唯一标识
        user.setTraceId(traceId);
        // 操作系统
        user.setOs(userAgent.getOperatingSystem().getName());
        // 浏览器
        user.setBrowser(userAgent.getBrowser().getName());
        // 设置登录追踪值
        SecurityContext.setTraceId(traceId);
    }
}
